#include <iostream>
#include <cerrno>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
#include "thread_pool.hpp"
#include "Task.hpp"

using namespace std;
using namespace ns_thread_pool;
using namespace ns_task;

// void serviceIO(int new_sock)
// {
//     while(true)
//     {
//         char buffer[1024];
//         memset(buffer, 0, sizeof(buffer));
//         ssize_t s = read(new_sock, buffer, sizeof(buffer) - 1);
//         if(s > 0)
//         {
//             buffer[s] = 0;//将我们获取的内容当成字符串
//             cout << "client# " << buffer << endl;
//             string echo_string = ">>>server<<<, ";
//             echo_string += buffer;

//             write(new_sock, echo_string.c_str(), echo_string.size());
//         }
//         else if(s == 0)
//         {
//             cout << "client quit ... " << endl;
//             break;
//         }
//         else
//         {
//             cout << "read error ... " << endl;
//             break;
//         }
//     }
// }

// void* HandlerRequest(void* args)
// {
//     pthread_detach(pthread_self());
//     int sock = *(int*)args;
//     delete (int*)args;

//     serviceIO(sock);
//     close(sock);
// }

int main(int argc, char*argv[])
{
    if(argc != 2)
    {
        cout << "Useage: \n\t" << "server_port" << endl;
        return 1;
    }
    //1.创建套接字
    int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if(listen_sock < 0)
    {
        cerr << "socket error: " << errno << endl;
        return 2;
    }

    //2.bind
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[1]));
    local.sin_addr.s_addr = INADDR_ANY;

    if(bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0)
    {
        cerr << "bind error: " << errno << endl;
        return 3;
    }

    //3.建立连接，因为tcp是面向连接的，a.在通信前，需要建立连接 b.然后才能通信
    //一定有人主动建立连接（客户端，需要服务），一定有人被动接受连接（服务器，提供服务）
    //我们当前写的是server，是周而复始的不间断的等待客户到来

    //设置套接字是Listen状态，本质是允许用户连接的

    const int back_log = 5;
    if(listen(listen_sock, back_log) < 0)
    {
        cout << "listen error: " << errno << endl;
        return 4;
    }

    //signal(SIGCHLD, SIG_IGN);//在Linux当中父进程忽略掉子进程的SIGCHID信号，子进程会自动退出释放资源。
    while(1)
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int new_sock = accept(listen_sock, (struct sockaddr*)&peer, &len);//返回值为文件描述符
        if(new_sock < 0)
        {
            continue;
        }

        uint16_t cli_port = ntohs(peer.sin_port);
        string cli_ip = inet_ntoa(peer.sin_addr);
        cout << "get a new link-> : [" << cli_ip << " ; " << cli_port << "]# " << new_sock << endl;

        //version 4：进程或者线程池
        //1.构建一个任务
        Task t(new_sock);
        
        //将任务push到后端的线程池中
         ThreadPool<Task> tp;
         tp.PushTask(t);






        //version2,3 有两个问题
        //1. 创建线程、进程无上限
        //2.当客户连接来了，我们才给客户创建进程/线程

        // //version 3 多线程版本
        // pthread_t tid;
        // int* pram = new int(new_sock);
        // pthread_create(&tid, nullptr, HandlerRequest, pram);

        // //version 2 -> 2.1 多进程版本
        // pid_t id = fork();

        // if(id < 0)
        // {
        //     continue;
        // }
        // else if(id == 0)//曾今被父进程打开的fd会被子进程继承（写时拷贝）
        // {
        //     //child
        //     close(listen_sock);

        //     if(fork() > 0)
        //     {
        //         exit(0);//退出子进程
        //     }
        //     //像后面走的是孙子进程，变成了孤儿进程，被OS"领养"
        //     serviceIO(new_sock);
        //     close(new_sock);
        //     exit(0);
        // }
        // else
        // {
        //     //father
        //     //do nothing!!
        //     waitpid(id, nullptr, 0);//子进程退出了，等待子进程。
        //     close(new_sock);
        // }
        // //version 1,单进程版
        // //4.提供服务
        // //serviceIO(new_sock);

     }
    return 0;
}
